package com.wiscamp.ninechapters.panels.application.services;

import com.wiscamp.ninechapters.panels.application.assemblers.OrganizationAssembler;
import com.wiscamp.ninechapters.panels.application.command.CreateOrganizationCommand;
import com.wiscamp.ninechapters.panels.application.command.UpdateOrganizationCommand;
import com.wiscamp.ninechapters.panels.application.vo.OrganizationVO;
import com.wiscamp.ninechapters.panels.domain.repositories.OrganizationRepository;
import com.wiscamp.ninechapters.panels.domain.services.OrganizationService;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.common.query.PagedObjects;
import cube.ddd.common.query.PagedQuery;
import cube.ddd.application.BaseAppService;
import cube.ddd.application.command.DeleteCommand;
import cube.ddd.application.command.DisableCommand;
import cube.ddd.application.command.EnableCommand;
import cube.ddd.utils.AppServiceUtils;
import jakarta.validation.Valid;
import org.springframework.stereotype.Service;

import java.util.Collection;

@Service
public class OrganizationAppService extends BaseAppService {

    private final OrganizationRepository organizationRepository;

    private final OrganizationService organizationService;

    public OrganizationAppService(OrganizationRepository organizationRepository, OrganizationService organizationService) {
        this.organizationRepository = organizationRepository;
        this.organizationService = organizationService;
    }

    @HandleServiceException
    public OrganizationVO getOrganization(long organizationId) {
        return AppServiceUtils.getById(organizationId, organizationService::getOrganization,
                OrganizationAssembler.Instance::toOrganizationVO);
    }

    @HandleServiceException
    public OrganizationVO getOrganizationByCode(String organizationCode) {
        return AppServiceUtils.getByText(organizationCode, organizationRepository::getOrganizationByCode,
                OrganizationAssembler.Instance::toOrganizationVO);
    }

    @HandleServiceException
    public OrganizationVO getOrganizationByName(String organizationName) {
        return AppServiceUtils.getByText(organizationName, organizationRepository::getOrganizationByName,
                OrganizationAssembler.Instance::toOrganizationVO);
    }

    @HandleServiceException
    public Collection<OrganizationVO> getAvailableOrganizations() {
        return AppServiceUtils.getList(organizationRepository::getAvailableOrganizations,
                OrganizationAssembler.Instance::toOrganizationVO);
    }

    @HandleServiceException
    public PagedObjects<OrganizationVO> getOrganizationsByQuery(PagedQuery pagedQuery) {
        var pagedObjects = organizationRepository.getOrganizationsByQuery(pagedQuery);
        return AppServiceUtils.convertPagedObjects(pagedObjects, OrganizationAssembler.Instance::toOrganizationVO);
    }

    @HandleServiceException
    public OrganizationVO createOrganization(@Valid CreateOrganizationCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.createOrUpdateBy(command, command.getOperatorId(), organizationService::createOrganization,
                OrganizationAssembler.Instance::toOrganizationVO, OrganizationAssembler.Instance::fromCreateCommand);
    }

    @HandleServiceException
    public OrganizationVO updateOrganization(@Valid UpdateOrganizationCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.createOrUpdateBy(command, command.getOperatorId(), organizationService::updateOrganization,
                OrganizationAssembler.Instance::toOrganizationVO, OrganizationAssembler.Instance::fromUpdateCommand);
    }

    @HandleServiceException
    public boolean deleteOrganization(@Valid DeleteCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.delete(command.getId(), command.getOperatorId(), organizationService::deleteOrganization);
    }

    @HandleServiceException
    public boolean enableOrganization(@Valid EnableCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.enable(command.getId(), command.getOperatorId(), organizationService::enableOrganization);
    }

    @HandleServiceException
    public boolean disableOrganization(@Valid DisableCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.disable(command.getId(), command.getOperatorId(), organizationService::disableOrganization);
    }
}
